/*
  使用集合实现斗地主游戏的部分功能，要求如下：

   （1）首先准备 54 张扑克牌并打乱顺序。

   （2）由三个玩家交替摸牌，每人 17 张扑克牌，最后三张留作底牌。

   （3）查看三个玩家手中的扑克牌和底牌。

   （4）其中玩家手中的扑克牌需要按照大小顺序打印，规则如下：

      手中扑克牌从大到小的摆放顺序：大王,小王,2,A,K,Q,J,10,9,8,7,6,5,4,3


  我的做法：
  1  定义扑克牌Card类
    1.1  扑克牌中又有花色，和点数两种特征，因此做了两个枚举类，点数Rank和花色Suit
    1.2  为了方便转化为字符串打印和比较大小排序，Rank和Suit中写了一些常用的static函数，Rank类中给每个枚举对象都设置了value值，方便比较
    1.3  在Rank枚举类中，从大到小设计 大王,小王,2,A,K,Q,J,10,9,8,7,6,5,4,3 的value值，就可以在排序时直接比较
    1.4  Card类通过给出的花色和点数生成扑克牌，同时考虑到了大小王没有花色的问题
  2  玩家Player类
    2.1  在扑克游戏中，玩家负责接收下发的扑克，并排序自己的手牌
    2.2  PLayer类中的手牌使用链表实现
    2.3  每个玩家拥有一个getCard函数，在每次拿到手牌时，按照value比较大小并插入手牌链表
  3  Game类，负责控制游戏的进程，游戏大致可以分为以下几个步骤
    3.1  生成扑克牌
    3.2  生成3个玩家Player
    3.3  play函数开始游戏，每一轮游戏都会进行洗牌shuffle，发牌deal，看牌show。这里题目要求只进行了一轮游戏
      3.3.1  洗牌：牌堆由于是集合，本身就是乱序的（哈希序），可以使用但是并不是随机的，且每次不会发生变化。因此我创建一个洗过牌的牌堆，使用
             ArrayList实现，调用了Collections自带的shuffle函数
      3.3.2  发牌：三个Player每人一张，调用的是Player自身的拿牌函数
      3.3.3  看牌：调用的是每个玩家的展示手牌函数，并最后展示底牌
 */

package com.syxbyi._3game;

import java.util.*;

public class Game {
    Set<Card> cards = new HashSet<>();
    List<Card> shuffledCards;
    Player[] players = new Player[3];

    public Game() {
        // gen cards
        for (int i = 1; i <= 13; i++) {
            Rank r = Rank.valueOf(i);
            for (Suit s: Suit.values()) {
                Card c = new Card(r, s);
                cards.add(c);
            }
        }
        cards.add(new Card(Rank.BLACK));
        cards.add(new Card(Rank.JOKER));
        // gen players
        for (int i = 0; i < players.length; i++) {
            players[i] = new Player();
        }
        // start game
        play();
    }

    public void play() {
        shuffle();
        deal();
        show();
    }

    // 洗牌
    private void shuffle() {
        // 先通过set创建一个临时list，然后使用collections中的打乱方法使list乱序
        shuffledCards = new ArrayList<>(cards);
        Collections.shuffle(shuffledCards);
        System.out.println("洗牌后牌堆为：");
        showAllCards(shuffledCards);
    }

    // 发牌
    private void deal() {
        int i = 0;
        while (i < 51) {
            players[i % 3].getCard(shuffledCards.get(i));
            i++;
        }
    }

    // 展示所有人的手牌和底牌
    public void show() {
        for (int i = 0; i < players.length; i++) {
            System.out.printf("玩家%d的手牌为：\n", i+1);
            showAllCards(players[i].getMyCards());
        }
        System.out.println("底牌为：");
        showAllCards(shuffledCards.subList(51, 54));
    }

    // 集合序打印所有扑克牌，乱序但不随机
    public void showAllCards() {
        showAllCards(cards);
    }

    // 打印指定集合中的卡牌
    public void showAllCards(Collection<Card> collection) {
        showAllCards(collection, 9);
    }

    // 打印卡牌，可以指定打印矩阵的列数
    public void showAllCards(Collection<Card> collection, int columns) {
        int i = 0;
        for (Card c: collection) {
            String cardToString = c.toString().length() > 2 ? c.toString() : c + " ";       // 为了小王大王能和其他对齐
            System.out.printf("%s\t", cardToString);
            if (++i % columns == 0) {
                System.out.println();
            }
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Game g = new Game();
    }
}
